<script lang="ts" setup>
import { reactive, ref, useTemplateRef, onMounted, nextTick, watch } from 'vue'
const dialogTableVisible = defineModel('dialogTableVisible')
const sliderFlag = defineModel('sliderFlag')
const myCanvas: any = useTemplateRef('myCanvas')
const myCanvas2: any = useTemplateRef('myCanvas2')
const container: any = useTemplateRef('containerRef')
const slider: any = useTemplateRef('sliderRef')
const sliderMaskRef: any = useTemplateRef('sliderMaskRef')
const dialogFooter: any = useTemplateRef('dialogFooter')
const tip = ref('')
const src =
  'https://img0.baidu.com/it/u=3509659753,2048716644&fm=253&fmt=auto&app=120&f=JPEG?w=667&h=500'
// onMounted(()=>{
// })
const toggleClass = ref('')
//获取指定区间的随机数
const getRandomNumber = (min: number, max: number) => {
  return Math.floor(Math.random() * (max - min) + min)
}
const l = 42 //滑块长度
const r = 10 //滑块圆角
const ll = l + r * 2 //滑块实际边长
let x = 0
let y = 0
let canvas: any = ''
let canvas2: any = ''
let ctx: any = ''
let ctx2: any = ''
watch(
  () => dialogTableVisible.value,
  (newVal, oldVal) => {
    if (newVal) {
      nextTick(() => {
        canvas = myCanvas.value
        canvas2 = myCanvas2.value

        //先给高度才能附上值，先给宽度高度是默认的150
        canvas.height = canvas.clientHeight
        canvas.width = canvas.clientWidth

        canvas2.height = canvas.clientHeight
        canvas2.width = canvas.clientWidth
        // canvas.width = 300;
        // canvas.height = 150;
        // canvas2.width = 300;
        // canvas2.height = 150;
        // console.log(22313, canvas.height, canvas2.height);
        // console.log( canvas.clientHeight, canvas2.clientHeight);

        x = getRandomNumber(ll + 10, canvas.width - (ll + 10))
        y = getRandomNumber(10 + r * 2, canvas.height - (ll + 10))
        // console.log(11,x, y);

        ctx = canvas.getContext('2d')
        ctx2 = canvas2.getContext('2d')
        ctx.willReadFrequently = true
        ctx2.willReadFrequently = true
        drawImage(ctx, src, canvas)
        drawImage(ctx2, src, canvas2, true)
        // drawPath(ctx, ctx2); // 画出遮罩层及滑块
        drawPath(ctx, 'fill', x, y) // 画出遮罩层及滑块
        drawPath(ctx2, 'clip', x, y) // 画出遮罩层及滑块
      })
    }
  },
)

// canvas上加上图片
const drawImage = (ctx: any, src: string, obj: any, copy?: any) => {
  const img = new Image() // 创建新的图片对象
  //解决跨域问题
  img.setAttribute('crossOrigin', 'Anonymous')
  img.src = src // 设置图片路径

  img.onload = function () {
    // console.log(334, canvas.height);

    ctx.drawImage(img, 0, 0, canvas.width, canvas.height) // 在canvas上绘制图片
    if (copy) {
      // console.log(445, canvas.height, canvas2.height);
      // console.log( canvas.clientHeight, canvas2.clientHeight);
      const imageData = ctx.getImageData(x, y - r * 2, ll, ll)
      obj.width = ll
      obj.style.width = ll + 'px'
      obj.style.height = canvas.clientHeight + 'px'
      obj.height = canvas.clientHeight
      ctx.putImageData(imageData, 0, y - r * 2)
    }
  }
}
// 画出遮罩层及滑块
const drawPath = (ctx: any, option: string, x: number, y: number) => {
  // console.log('1111');
  console.log('222', option, x, y)

  // ctx.beginPath();//开始绘制
  // ctx.arc(x,y,r,start,stop,boolean);//画圆
  // ctx.fill();//填充颜色
  // ctx.stroke();//绘制
  // ctx.closePath();//结束绘制
  // ctx.moveTo(x,y);// 移动到指定坐标
  // ctx.lineTo(x,y);// 从当前位置画线到指定坐标
  // ctx.clearRect(0, 0, 300, 150); // 清除画布
  // ctx.fillRect(10,10,150,80); // 绘制矩形
  // ------------------

  // ctx.beginPath(); // 开始绘制
  // ctx.moveTo(50, 50); // 移动到指定坐标
  // ctx.arc(71, 43, 9, 0.72 * Math.PI, 2.26 * Math.PI);
  // ctx.lineTo(92, 50); // 从当前位置画线到指定坐标
  // ctx.arc(100, 69, 9, 1.21 * Math.PI, 2.78 * Math.PI);

  // ctx.lineTo(92, 92);
  // ctx.lineTo(50, 92);
  // ctx.arc(57, 69, 9, 2.76 * Math.PI, 1.24 * Math.PI, true);
  // ctx.lineTo(50, 50);
  // ctx.lineWidth = 1;//   设置线宽
  // // ctx.fillStyle = 'rgba(255, 255, 255, 1)'; // 设置填充颜色
  // ctx.fillStyle = 'rgba(255, 255, 255, 1)'; // 设置填充颜色
  // ctx.strokeStyle = 'rgba(255, 255, 255, 1)'; // 填充颜色
  // // ctx.strokeStyle = 'red'; // 填充颜色
  // ctx.stroke();
  // ctx.globalCompositeOperation = 'destination-over';//设置合成方式
  // ctx.fill(); // 填充颜色
  // //
  // ctx2.beginPath(); // 开始绘制
  // ctx2.moveTo(50, 50); // 移动到指定坐标
  // ctx2.arc(71, 43, 9, 0.72 * Math.PI, 2.26 * Math.PI);
  // ctx2.lineTo(92, 50); // 从当前位置画线到指定坐标
  // ctx2.arc(100, 69, 9, 1.21 * Math.PI, 2.78 * Math.PI);

  // ctx2.lineTo(92, 92);
  // ctx2.lineTo(50, 92);
  // ctx2.arc(57, 69, 9, 2.76 * Math.PI, 1.24 * Math.PI, true);
  // ctx2.lineTo(50, 50);
  // ctx2.lineWidth = 0.01;//   设置线宽
  // // ctx.fillStyle = 'rgba(255, 255, 255, 1)'; // 设置填充颜色
  // // ctx2.fillStyle = 'rgba(255, 255, 255, 0)'; // 设置填充颜色
  // ctx2.strokeStyle = 'rgba(255, 255, 255, 1)'; // 填充颜色
  // // ctx.strokeStyle = '#fff'; // 填充颜色
  // ctx2.stroke();
  // ctx2.globalCompositeOperation = 'destination-over';//设置合成方式
  // // ctx2.fill(); // 填充颜色
  // ctx2.clip();//裁剪

  // 第一个圆
  ctx.beginPath() // 开始绘制
  ctx.moveTo(x, y)
  ctx.arc(x + l / 2, y - r + 2, r, 0.72 * Math.PI, 2.26 * Math.PI)
  ctx.lineTo(x + l, y)
  ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * Math.PI, 2.78 * Math.PI)
  ctx.lineTo(x + l, y + l)
  ctx.lineTo(x, y + l)
  ctx.arc(x + r - 2, y + l / 2, r, 2.76 * Math.PI, 1.24 * Math.PI, true)
  ctx.lineTo(x, y)
  ctx.lineWidth = 1 //   设置线宽
  ctx.fillStyle = 'rgba(255, 255, 255, 1)' // 设置填充颜色
  ctx.strokeStyle = 'rgba(255, 255, 255, 1)' // 填充颜色
  ctx.stroke()
  ctx.globalCompositeOperation = 'destination-over' //设置合成方式
  ctx[option]() // 填充颜色
}
const draw = (ctx: any, option: string, x: number, y: number) => {
  ctx.beginPath() // 开始绘制
  ctx.moveTo(x, y)
  ctx.lineTo(x + l / 2, y)
  ctx.arc(x + l / 2, y - r + 2, r, 0.2 * Math.PI, 0.2 * Math.PI)
  ctx.lineTo(x + l / 2, y)
  ctx.lineTo(x + l, y)
  ctx.lineTo(x + l, y + l / 2)
  ctx.arc(x + l + r - 2, y + l / 2, r, 0.2 * Math.PI, 0.2 * Math.PI)
  ctx.lineTo(x + l, y + l / 2)
  ctx.lineTo(x + l, y + l)
  ctx.lineTo(x, y + l)
  ctx.lineTo(x, y)
  ctx.fillStyle = '#fff' // 设置填充颜色
  ctx.beginPath()
  ctx.arc(x, y + l / 2, r, 1.5 * Math.PI, 0.5 * Math.PI)
  ctx.strokeStyle = 'rgba(255, 255, 255, 1)' // 填充颜色
  ctx.stroke()
  ctx.globalCompositeOperation = 'xor' //设置合成方式
  ctx[option]() // 填充颜色
}
const isDragging = ref(false)
const sliderText = ref(false)
const handleMouseDown = (e: any) => {
  isDragging.value = true
  toggleClass.value = 'slider-container-avtive'
  sliderText.value = true
  // originX = e.clientX;
  // originY = e.clientY;
}
const handleMouseUp = (e: any) => {
  if (!isDragging.value) {
    return
  }
  isDragging.value = false
  toggleClass.value = ''
  const spliced: boolean = verify()
  if (spliced) {
    toggleClass.value = 'slider-container-success' //   滑块成功
    success()
  } else {
    toggleClass.value = 'slider-container-fail' //   滑块失败成功
    failed()
    setTimeout(() => {
      reset()
    }, 1000)
  }
}
const handleMouseMove = (e: any) => {
  nextTick(() => {
    if (isDragging.value) {
      const containerRect = container.value.getBoundingClientRect()
      const sliderRect = slider.value.getBoundingClientRect()
      // const moveX = e.clientX - originX;// 滑块移动的距离
      // const moveY = e.clientX - originY; // 滑块移动的距离
      const offsetX = e.clientX - containerRect.left - sliderRect.width / 2
      const maxX = containerRect.width - sliderRect.width
      if (offsetX < 0 || offsetX + 56 >= myCanvas.value?.width) {
        return false // 阻止滑块超出范围
      }
      // toggleClass.value = 'slider-container-avtive'; // 添加滑块移动的样式
      myCanvas2.value.style.left = offsetX + 'px' // 滑块移动
      sliderMaskRef.value.style.width = offsetX + 'px' // 滑块移动
      slider.value.style.left = `${Math.max(0, Math.min(offsetX, maxX))}px` // 滑块移动
      // console.log("@@@@11111111", moveX, moveY);
      // const offsetX = e.clientX - containerRect.left - sliderRect.width / 2;
      // const maxX = containerRect.width - sliderRect.width;
      // slider.style.left = `${Math.max(0, Math.min(offsetX, maxX))}px`;
    }
  })
}
//
const verify = (): boolean => {
  const left = parseInt(myCanvas2.value.style.left)
  console.log('verify', left - x)

  return Math.abs(left - x) < 10
}
const success = () => {
  tip.value = '验证成功'
  dialogFooter.value.style.color = 'green'
  setTimeout(() => {
    dialogTableVisible.value = false
    sliderFlag.value = true
    reset()
  }, 1000)

  // if(){
  //   tip.value="验证成功";
  // }
}
const failed = () => {
  tip.value = '验证失败'
  dialogFooter.value.style.color = 'red'
}
const reset = () => {
  myCanvas2.value.style.left = 0
  sliderMaskRef.value.style.left = 0
  toggleClass.value = ''
  slider.value.style.left = 0
  sliderMaskRef.value.style.width = 0
  tip.value = ''
  dialogFooter.value.style.color = ''
  // console.log("reset", ctx,ctx2);

  ctx.clearRect(0, 0, canvas.width, canvas.clientHeight) // 清除画布上的内容
  ctx2.clearRect(0, 0, canvas.width, canvas.clientHeight) // 清除画布上的内容
  canvas2.width = canvas.clientWidth
  canvas2.style.width = canvas.clientWidth + 'px'
  x = getRandomNumber(ll + 10, canvas.width - (ll + 10))
  y = getRandomNumber(10 + r * 2, canvas.height - (ll + 10))
  drawImage(ctx, src, canvas)
  drawImage(ctx2, src, canvas2, true) // 重新绘制
  drawPath(ctx, 'fill', x, y) // 重新绘制
  drawPath(ctx2, 'clip', x, y) // 重新绘制
}
</script>
<template>
  <el-dialog
    v-model="dialogTableVisible"
    width="50%"
    title="请完成下列验证后继续"
    @mouseup="handleMouseUp"
    @mousemove="handleMouseMove"
  >
    <div class="canvas">
      <canvas class="bg" ref="myCanvas"></canvas>
      <div class="Refresh">
        <el-icon>
          <Refresh />
        </el-icon>
      </div>
      <canvas ref="myCanvas2" class="bg canvs2"></canvas>
    </div>

    <div class="slider-container" :class="toggleClass" ref="containerRef">
      <div class="slider-mask" ref="sliderMaskRef">
        <div class="slider" ref="sliderRef" @mousedown="handleMouseDown">
          <el-icon>
            <Right />
          </el-icon>
        </div>
      </div>
      <span :class="{ 'slider-text': sliderText }">向右滑动滑块填充拼图</span>
    </div>
    <template #footer>
      <span ref="dialogFooter" v-html="tip"></span>
    </template>
  </el-dialog>
</template>
<style lang="scss" scoped>
// .title {
//   font-size: 16px;
// }

.canvas {
  width: 100%;
  // width: 300px;
  position: relative;
  // overflow: hidden;

  .bg {
    width: 100%;
    // height: 120px;
    // background-color: #f5f5f5;
    // background-color: red;
    border-radius: 10px;
    vertical-align: middle;
  }

  .canvs2 {
    position: absolute;
    top: 0px;
    left: 0px;
  }

  .Refresh {
    position: absolute;
    top: 10px;
    right: 10px;
    font-size: 20px;
    color: #999;
    cursor: pointer;
  }
}

.slider-container {
  width: 100%;
  // width: 300px;
  // height: 30px;
  // background-color: #fff;
  margin-top: 15px;
  position: relative;
  text-align: center;
  height: 30px;
  line-height: 30px;
  background-color: #f7f9fa;
  color: #45454c;
  border: 1px solid #e4e7eb;

  .slider-mask {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;

    background-color: #1991fa;
    background-color: #d1e9fe;

    .slider {
      position: absolute;
      left: 0;
      top: 0;
      height: 30px;
      width: 30px;
      background-color: #fff;
      box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
      cursor: pointer;
      transition: background 0.3s linear;
      display: flex;
      align-items: center;
      justify-items: center;

      &:hover {
        background: #1991fa;
      }

      &:hover .el-icon {
        color: #fff;
      }

      .el-icon {
        font-size: 20px;
        flex: 1;
      }
    }
  }

  .slider-text {
    display: none;
  }
}

.slider-container-acitve {
  .slider-mask {
    height: 28px;
    border-width: 1px;

    .slider {
      height: 28px;
      top: -1px;
      border: 1px solid #1991fa;
      display: flex;
      align-items: center;
      justify-items: center;

      .el-icon {
        font-size: 26px;
        flex: 1;
      }
    }
  }
}

.slider-container-success {
  .slider-mask {
    height: 28px;
    border: 1px solid #52ccba;
    background: 1px solid #d2f4ef;

    .slider {
      height: 28px;
      top: -1px;
      border: 1px solid #52ccba;
      background-color: #52ccba !important;

      .el-icon {
        color: #fff;
      }
    }
  }

  .slider-text {
    display: none;
  }
}

.slider-container-fail {
  .slider-mask {
    height: 28px;
    border: 1px solid #f57a7a;
    background: 1px solid #fce1e1;

    .slider {
      height: 28px;
      top: -1px;
      border: 1px solid #f57a7a;
      background-color: #f57a7a !important;

      .el-icon {
        color: #fff;
      }
    }
  }
}
</style>
